package edu.kufpg.armatus.networking;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.util.Log;
import edu.kufpg.armatus.DeviceConstants;
import edu.kufpg.armatus.Prefs;
import java.io.IOException;
import java.util.UUID;
/**
* Utility class that organizes all of the crazy Android Bluetooth API calls into much
* more intuitive method names.
*/
public final class BluetoothUtils {
/**
* A wrapper around a 128-bit number used to identify this service. This UUID is the Bluetooth
* Base UUID and is commonly used for simple Bluetooth applications. Regardless of the UUID used,
* it must match the one that the Armatus Bluetooth server is advertising.
* */
public static final UUID BASE_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
/** Request code for prompting the user to enable Bluetooth. */
public static final int REQUEST_ENABLE_BLUETOOTH = 8675309;
/** Request code for prompting the user to select a Bluetooth device from a list of nearby
* devices. */
public static final int REQUEST_FIND_BLUETOOTH_DEVICE = 777;
/** Identifies this class for {@link Log} purposes. */
private static final String TAG = BluetoothUtils.class.getSimpleName();
/** Reference to the device's Bluetooth adapter. */
private static BluetoothAdapter sAdapter;
private static BluetoothDevice sDevice;
private static BluetoothSocket sSocket;
private static boolean sLastConnectionFailed = false;
private BluetoothUtils() {}
public static void closeBluetooth() {
if (sSocket != null) {
try {
// if (sSocket.getOutputStream() != null) {
// sSocket.getOutputStream().close();
// }
// if (sSocket.getInputStream() != null) {
// sSocket.getInputStream().close();
// }
sSocket.close();
} catch (IOException e) {
Log.w(TAG, "Error occurred when closing Bluetooth socket!");
e.printStackTrace();
}
sSocket = null;
}
sDevice = null;
}
/**
* If Bluetooth is not already on, this method prompts the user to turn on Bluetooth.
* @param activity The {@link Activity} that will handle the result (with the {@code
* requestCode} {@link #REQUEST_ENABLE_BLUETOOTH}).
*/
public static void enableBluetooth(Activity activity) {
if (getBluetoothAdapter(activity) != null) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BLUETOOTH);
} else {
Log.w(TAG, "Cannot enable Bluetooth (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
}
}
/**
* If Bluetooth is not already on, this method prompts the user to turn on Bluetooth.
* @param fragment The {@link Fragment} that will handle the result (with the {@code
* requestCode} {@link #REQUEST_ENABLE_BLUETOOTH}).
*/
public static void enableBluetooth(Fragment fragment) {
if (getBluetoothAdapter(fragment.getActivity()) != null) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
fragment.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BLUETOOTH);
} else {
Log.w(TAG, "Cannot enable Bluetooth (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
}
}
/**
* Retrieves the device's Bluetooth adapter (if it supports Bluetooth).
* @param context The {@link Context} to use.
* @return the default Bluetooth adapter, or {@code null} if the device does not support
* Bluetooth.
*/
@SuppressLint({ "InlinedApi", "NewApi" })
public static BluetoothAdapter getBluetoothAdapter(Context context) {
if (sAdapter == null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
sAdapter = BluetoothAdapter.getDefaultAdapter();
} else {
final BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
sAdapter = manager.getAdapter();
}
}
if (sAdapter == null) {
Log.w(TAG, "Bluetooth is not supported on this " + DeviceConstants.DEVICE_NAME + '!');
}
return sAdapter;
}
/**
* Retrieves the {@code BluetoothDevice} as specified by the app's {@link SharedPreferences}.
* @param context The {@link Context} to use.
* @return The {@code BluetoothDevice} corresponding to user preferences. {@code null} is
* returned if no {@code BluetoothDevice} is found in user preferences or if Bluetooth is
* not supported on the device.
*/
public static BluetoothDevice getBluetoothDevice(Context context) {
String address = Prefs.getBluetoothDeviceAddress(context);
if (address != null) {
BluetoothAdapter adapter = getBluetoothAdapter(context);
if (adapter != null) {
if (sDevice == null) {
sDevice = adapter.getRemoteDevice(address);
}
return sDevice;
} else {
Log.w(TAG, "Cannot get Bluetooth device (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
return null;
}
} else {
Log.w(TAG, "Cannot get Bluetooth device (no device address found in preferences).");
return null;
}
}
public static BluetoothSocket getBluetoothSocket(Context context) {
BluetoothAdapter adapter = getBluetoothAdapter(context);
if (adapter != null) {
BluetoothDevice device = getBluetoothDevice(context);
if (device != null) {
if (sSocket == null) {
try {
sSocket = device.createRfcommSocketToServiceRecord(BASE_UUID);
} catch (IOException e) {
e.printStackTrace();
Log.w(TAG, "Cannot get Bluetooth socket (creation failed).");
return null;
}
}
return sSocket;
} else {
Log.w(TAG, "Cannot get Bluetooth socket (no device address found in preferences).");
return null;
}
} else {
Log.w(TAG, "Cannot get Bluetooth socket (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
return null;
}
}
/**
* Starts an {@link Intent} that allows the user to select a Bluetooth device from a list
* of nearby devices.
* @param activity The {@link Activity} that will handle the result (with the {@code
* requestCode} {@link #REQUEST_FIND_BLUETOOTH_DEVICE}).
*/
public static void findDeviceName(Activity activity) {
if (getBluetoothAdapter(activity) != null) {
Intent findBtDevicesIntent = new Intent(activity, BluetoothDeviceListActivity.class);
activity.startActivityForResult(findBtDevicesIntent, REQUEST_FIND_BLUETOOTH_DEVICE);
} else {
Log.w(TAG, "Cannot find Bluetooth device names (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
}
}
/**
* Starts an {@link Intent} that allows the user to select a Bluetooth device from a list
* of nearby devices.
* @param fragment The {@link Fragment} that will handle the result (with the {@code
* requestCode} {@link #REQUEST_FIND_BLUETOOTH_DEVICE}).
*/
public static void findDeviceName(Fragment fragment) {
if (getBluetoothAdapter(fragment.getActivity()) != null) {
Intent findBtDevicesIntent = new Intent(fragment.getActivity(), BluetoothDeviceListActivity.class);
fragment.startActivityForResult(findBtDevicesIntent, REQUEST_FIND_BLUETOOTH_DEVICE);
} else {
Log.w(TAG, "Cannot find Bluetooth device names (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
}
}
@SuppressWarnings("resource")
public static boolean isBluetoothConnected(Context context) {
BluetoothAdapter adapter = getBluetoothAdapter(context);
if (adapter != null) {
BluetoothDevice device = getBluetoothDevice(context);
if (device != null) {
BluetoothSocket socket = getBluetoothSocket(context);
if (socket != null) {
return socket.isConnected();
} else {
Log.w(TAG, "Cannot determine Bluetooth state (socket creation failed).");
return false;
}
} else {
Log.w(TAG, "Cannot determine Bluetooth state (no device found in preferences).");
return false;
}
} else {
Log.w(TAG, "Cannot determine Bluetooth state (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
return false;
}
}
/**
* Returns whether Bluetooth is turned on.
* @param context The {@link Context} to use.
* @return {@code true} if Bluetooth is on, or {@code false} if Bluetooth is off or not
* supported on the device.
*/
public static boolean isBluetoothEnabled(Context context) {
BluetoothAdapter adapter = getBluetoothAdapter(context);
if (adapter != null) {
return adapter.isEnabled();
} else {
Log.w(TAG, "Cannot determine Bluetooth state (Bluetooth not supported on this "
+ DeviceConstants.DEVICE_NAME + ").");
return false;
}
}
public static boolean lastConnectionFailed() {
return sLastConnectionFailed;
}
public static void notifyLastConnectionFailed() {
sLastConnectionFailed = true;
}
public static void notifyLastConnectionSucceeded() {
sLastConnectionFailed = false;
}
}